#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "app_oled.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "cJSON.h"
#include "app_http.h"
#include "ds18b20.h"
static const char* TAG = "OLED_DERVICE";
i2c_cmd_handle_t cmd;
bool OLED_INIT_OK = false;
/**
 * @brief I2C初始化函数
 *
 */
static void i2c_init(void)
{
    i2c_config_t app_i2c_config = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = OLED_SDA_PIN,
        .scl_io_num = OLED_SCL_PIN,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .clk_stretch_tick = 100000,
    };
    i2c_driver_install(I2C_NUM_0, app_i2c_config.mode);
    i2c_param_config(I2C_NUM_0, &app_i2c_config);
}
/**
 * @brief i2c 写数据
 *
 * @param cmd 指令句柄
 * @param data 指令
 * @return esp_err_t
 */
static esp_err_t i2c_write_data(i2c_cmd_handle_t cmd, uint8_t data, bool cmd_status)
{
    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    ESP_ERROR_CHECK(i2c_master_write_byte(cmd, OLED_ADDRESS << 1 | I2C_MASTER_WRITE, true));
    if (cmd_status) {
        ESP_ERROR_CHECK(i2c_master_write_byte(cmd, 0x00, true));
    }
    else {
        ESP_ERROR_CHECK(i2c_master_write_byte(cmd, 0x40, true));
    }

    ESP_ERROR_CHECK(i2c_master_write_byte(cmd, data, true));
    ESP_ERROR_CHECK(i2c_master_stop(cmd));
    esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_RATE_MS);
    if (ret == ESP_OK);
    //ESP_LOGI(TAG, "i2c master writer %s", cmd_status ? "cmd" : "data");
    else
        ESP_LOGE(TAG, "i2c master writer failse:%d", ret);
    i2c_cmd_link_delete(cmd);

    return ESP_OK;
}

/**
 * @brief oled 设置光标
 *
 * @param x
 * @param y
 */
static void oled_set_pos(uint8_t x, uint8_t y)
{
    i2c_write_data(cmd, 0xb0 + y, WRITE_CMD);
    i2c_write_data(cmd, ((x & 0xf0) >> 4) | 0x10, WRITE_CMD);
    i2c_write_data(cmd, (x & 0x0f) | 0x01, WRITE_CMD);
}

/**
 * @brief OLED 初始化
 *
 */
void oled_init(void)
{
    vTaskDelay(500 / portTICK_RATE_MS);
    i2c_init();
    i2c_write_data(cmd, 0XAE, WRITE_CMD);

    i2c_write_data(cmd, 0x00, WRITE_CMD);
    i2c_write_data(cmd, 0x10, WRITE_CMD);

    i2c_write_data(cmd, 0x40, WRITE_CMD);

    // i2c_write_data(cmd, 0xB0, WRITE_CMD);

    i2c_write_data(cmd, 0x81, WRITE_CMD);//设置对比度
    i2c_write_data(cmd, 0xCF, WRITE_CMD);

    i2c_write_data(cmd, 0xa1, WRITE_CMD); //显示方向，A0为左右相反，A1为正常你
    i2c_write_data(cmd, 0xc8, WRITE_CMD);

    i2c_write_data(cmd, 0xa6, WRITE_CMD);

    i2c_write_data(cmd, 0xa8, WRITE_CMD);
    i2c_write_data(cmd, 0x3F, WRITE_CMD);//1/64 

   // i2c_write_data(cmd, 0xc8, WRITE_CMD); //显示方向，C0为上下相反，C8为正常
    //i2c_write_data(cmd, 0x81, WRITE_CMD);
   // i2c_write_data(cmd, 0xFe, WRITE_CMD); //亮度设置 越大越亮

    i2c_write_data(cmd, 0xD3, WRITE_CMD);
    i2c_write_data(cmd, 0x00, WRITE_CMD);

    i2c_write_data(cmd, 0xd5, WRITE_CMD); //set display clock divide ratio/oscillator frequency
    i2c_write_data(cmd, 0x80, WRITE_CMD); //--set divide ratio, Set Clock as 100 Frames/Sec

    i2c_write_data(cmd, 0xd9, WRITE_CMD);
    i2c_write_data(cmd, 0X1F, WRITE_CMD);

    i2c_write_data(cmd, 0xda, WRITE_CMD);//设置尺寸
    i2c_write_data(cmd, 0x12, WRITE_CMD); //12 为128*64  02为128*32

    i2c_write_data(cmd, 0xDB, WRITE_CMD);
    i2c_write_data(cmd, 0x40, WRITE_CMD);

    i2c_write_data(cmd, 0x20, WRITE_CMD);
    i2c_write_data(cmd, 0x02, WRITE_CMD);

    i2c_write_data(cmd, 0x8d, WRITE_CMD);
    i2c_write_data(cmd, 0x14, WRITE_CMD);

    i2c_write_data(cmd, 0xA4, WRITE_CMD); //打开显示器 A4为打开，A5为关闭
    i2c_write_data(cmd, 0xA6, WRITE_CMD); //设置显示方向 A6为正常，A7为反向
    i2c_write_data(cmd, 0xAf, WRITE_CMD);

    i2c_write_data(cmd, 0xAf, WRITE_CMD);
    oled_clear_display();
    oled_set_pos(0, 0);
}
/**
 * @brief oled 开启显示
 *
 */
void oled_display_ON(void)
{
    i2c_write_data(cmd, 0x8d, WRITE_CMD);
    i2c_write_data(cmd, 0x14, WRITE_CMD);
    i2c_write_data(cmd, 0xaf, WRITE_CMD);
}
/**
 * @brief 关闭显示
 *
 */
void oled_display_OFF(void)
{
    i2c_write_data(cmd, 0x8d, WRITE_CMD);
    i2c_write_data(cmd, 0x10, WRITE_CMD);
    i2c_write_data(cmd, 0xAE, WRITE_CMD);
}
/**
 * @brief OLED 清屏
 *
 */
void oled_clear_display(void)
{
    uint8_t n;
    for (int i = 0; i < 8; i++)
    {
        i2c_write_data(cmd, 0xb0 + i, WRITE_CMD);
        i2c_write_data(cmd, 0x00, WRITE_CMD);
        i2c_write_data(cmd, 0x10, WRITE_CMD);
        for (n = 0;n < 128;n++) i2c_write_data(cmd, 0x00, WRITE_DATA);
    }
}
/**
 * @brief 在某个位置，显示一个字符
 *
 * @param x x轴  0~128
 * @param y y轴  0~64
 * @param ch 字符
 */
void oled_show_char(uint8_t x, uint8_t y, unsigned char ch)
{
    uint8_t c = 0, i = 0;
    c = ch - ' ';
    if (x > 127) {
        x = 0;
        y = y + 1;
    }
    if (SIZE == 16) {
        oled_set_pos(x, y);
        for (i = 0; i < 8; i++)
            i2c_write_data(cmd, F8X16[c * 16 + i], WRITE_DATA);
        oled_set_pos(x, y + 1);
        for (i = 0;i < 8;i++)
            i2c_write_data(cmd, F8X16[c * 16 + i + 8], WRITE_DATA);
    }
    else {
        oled_set_pos(x, y + 1);
        for (i = 0;i < 6;i++)
            i2c_write_data(cmd, F6x8[c][i], WRITE_DATA);
    }
}/**
 * @brief oled 显示字符串
 *
 * @param x
 * @param ch
 */
void oled_show_str(unsigned char x, unsigned char y, char* str)
{
    unsigned int i = 0;
    while (str[i] != '\0')
    {
        oled_show_char(x, y, str[i]);
        x += 8;
        if (x > 120) { x = 0;y += 2; }
        i++;
    }
}
/**
 * @brief 显示一个中文
 *
 * @param x
 * @param y
 * @param N
 */
void oled_display_ch(unsigned char x, unsigned char y, unsigned char N)
{
    unsigned char wm = 0;
    unsigned int adder = 32 * N;
    oled_set_pos(x, y);
    for (wm = 0;wm < 16;wm++)
    {
        i2c_write_data(cmd, (uint8_t)F16x16[adder], WRITE_DATA);
        adder += 1;
    }
    oled_set_pos(x, y + 1);
    for (wm = 0;wm < 16;wm++)
    {
        i2c_write_data(cmd, (uint8_t)F16x16[adder], WRITE_DATA);
        adder += 1;
    }
}
/**
 * @brief 显示时间
 *
 * @param x
 * @param y
 * @param N
 */
void oled_display_time(unsigned char x, unsigned char y, unsigned char N)
{
    unsigned char wm = 0;
    unsigned int adder = 64 * N;
    oled_set_pos(x, y);
    for (wm = 0;wm < 16;wm++)
    {
        i2c_write_data(cmd, (uint8_t)F16x32[adder], WRITE_DATA);
        adder += 1;
    }

    oled_set_pos(x, y + 1);
    for (wm = 0;wm < 16;wm++)
    {
        i2c_write_data(cmd, (uint8_t)F16x32[adder], WRITE_DATA);
        adder += 1;
    }

    oled_set_pos(x, y + 2);
    for (wm = 0;wm < 16;wm++)
    {
        i2c_write_data(cmd, (uint8_t)F16x32[adder], WRITE_DATA);
        adder += 1;
    }
    oled_set_pos(x, y + 3);
    for (wm = 0;wm < 16;wm++)
    {
        i2c_write_data(cmd, (uint8_t)F16x32[adder], WRITE_DATA);
        adder += 1;
    }
}
/**
 * @brief 显示一张图片
 *
 * @param image 图片数据
 */
void oled_display_image(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1, unsigned char* image)
{
    unsigned int j = 0;
    unsigned char x, y;

    if (y1 % 8 == 0) y = y1 / 8;
    else y = y1 / 8 + 1;
    for (y = y0;y < y1;y++)
    {
        oled_set_pos(x0, y);
        for (x = x0;x < x1;x++)
        {
            i2c_write_data(cmd, image[j++], WRITE_DATA);
        }
    }
}
/**
 * @brief 显示时间
 *
 * @param x
 * @param y
 * @param timeinfo
 */
void oled_display_str_time(unsigned char x, unsigned char y, struct tm timeinfo)
{
    char time_buf[64];
    memset(time_buf, 0, 64);
    sprintf(time_buf, "%d/%02d/%02d", timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday);
    oled_show_str(0, y - 2, time_buf);
    oled_display_ch(strlen(time_buf) * 8, y - 2, 7);
    oled_display_ch(strlen(time_buf) * 8 + 16, y - 2, 8);
    oled_display_ch(strlen(time_buf) * 8 + 32, y - 2, timeinfo.tm_wday);

    oled_display_time(x, y, (int)timeinfo.tm_hour / 10);
    oled_display_time(x + 16, y, (int)timeinfo.tm_hour % 10);
    oled_display_time(x + 32, y, 10);
    oled_display_time(x + 48, y, (int)timeinfo.tm_min / 10);
    oled_display_time(x + 64, y, (int)timeinfo.tm_min % 10);
    oled_display_time(x + 80, y, 10);
    oled_display_time(x + 96, y, (int)timeinfo.tm_sec / 10);
    oled_display_time(x + 112, y, (int)timeinfo.tm_sec % 10);
}
/**
 * @brief OLED初始化显示
 *
 */
void oled_init_display(void)
{
    oled_init();
    oled_display_time(0, 2, 0);
    oled_display_time(16, 2, 1);
    oled_display_time(32, 2, 10);
    oled_display_time(48, 2, 0);
    oled_display_time(64, 2, 0);
    oled_display_time(80, 2, 10);
    oled_display_time(96, 2, 0);
    oled_display_time(112, 2, 0);
    oled_show_str(0, 0, "2021/09/25  ");
}
/**
 * @brief 解析天气数据
 *
 */
static void waether_cjson_analysis(void)
{
    long int cityid_num = 0;

    cJSON* root = cJSON_Parse(http_user_data);
    cJSON* cityid = cJSON_GetObjectItem(root, "cityid");
    cJSON* wea = cJSON_GetObjectItem(root, "wea");
    cJSON* tem = cJSON_GetObjectItem(root, "tem");
    cJSON* errcode = cJSON_GetObjectItem(root, "errcode");
    if (errcode != NULL) {
        ESP_LOGE(TAG, "http errcode: %d", errcode->valueint);
        char* errcode_str = NULL;
        errcode_str = malloc(32);
        sprintf(errcode_str, "http:errcode %d", errcode->valueint);
        oled_show_str(0, 0, errcode_str);
        free(errcode_str);
        return;
    }
    cityid_num = atol(cityid->valuestring);
    //显示城市,通过城市ID
    switch (cityid_num) {
        case 101280601:
            //显示深圳
            oled_display_ch(0, 6, 15);
            oled_display_ch(16, 6, 16);
            break;
            //显示广州
        case 101280101:
            oled_display_ch(0, 6, 31);
            oled_display_ch(16, 6, 32);
            break;
    }

    //显示天气
    if (!strncmp(wea->valuestring, "多云转晴", strlen("多云转晴"))) {
        oled_display_ch(40, 6, 19);
        oled_display_ch(56, 6, 20);
        oled_display_ch(72, 6, 21);
        oled_display_ch(88, 6, 22);
    }
    if (!strncmp(wea->valuestring, "多云", strlen("多云"))) {
        oled_display_ch(40, 6, 19);
        oled_display_ch(56, 6, 20);
    }
    if (!strncmp(wea->valuestring, "雨", strlen("雨"))) {
        oled_display_ch(40, 6, 23);
    }
    if (!strncmp(wea->valuestring, "大雨", strlen("大雨"))) {
        oled_display_ch(40, 6, 24);
        oled_display_ch(56, 6, 23);
    }
    if (!strncmp(wea->valuestring, "小雨", strlen("小雨"))) {
        oled_display_ch(40, 6, 25);
        oled_display_ch(56, 6, 23);
    }
    if (!strncmp(wea->valuestring, "阵雨", strlen("阵雨"))) {
        oled_display_ch(40, 6, 26);
        oled_display_ch(56, 6, 23);
    }
    if (!strncmp(wea->valuestring, "晴", strlen("晴"))) {
        oled_display_ch(40, 6, 22);
    }
    cJSON_Delete(root);
}
/**
 * @brief oled 显示任务
 *
 * @param arg
 */
void oled_display_task(void* arg)
{
    oled_init_display();
    OLED_INIT_OK = true;
    for (;;) {
        vTaskDelay(1000 / portTICK_RATE_MS);
        if (http_data_update_flag) {
            waether_cjson_analysis();
            http_data_update_flag = false;
        }

    }
}
